/**
 * 日志记录
 * appenders: {
 *  write: {
 *   type: 'console|file|dateFile',
 *   -- 1、console：即为控制台打印， 多数用于开发测试。
 *   -- 2、 file： 表示日志输出为普通文件， 在此种配置下日志会输出到目标文件夹的目标文件中， 并会随着文件大小的变化自动份文件。
 *   -- 3、 dateFile： 表示是输出按时间分文件的日志， 在此种配置下, 日志会输出到目标目录下， 并以时间格式命名， 随着时间的推移， 以时间格式命名的文件如果尚未存在， 则自动创建新的文件。
 *   filename: 日志文件路径。
 *   maxLogSize: 只在**type: file**模式有效，表示文件多大时才会创建下一个文件（ xxx.log .1 之类）单位是字节，实际设置时具体的值根据业务来定, 但是不推荐大于100Mb.。
 *   pattern: 只在**type: dateFile**模式有效， 表示一个文件的时间命名模式， 在生成文件中会依照pattern配置来在filename的文件结尾追加一个时间串来命名文件。
 *   alwaysIncludePattern: 只在**type: dateFile**模式有效，这个配置为ture.即最终的日志路径文件名为filename + pattern
 *   backups: 只在**type: file**模式有效，表示备份的文件数量，如果文件过多则会将最旧的删除
 *  }
 * }
 */
const log4js = require('log4js');

// log4js中日志级别
const LEVELS = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];

// @ts-ignore
const NODE_ENV = process.env.NODE_ENV || 'development';
module.exports = app => {
  const {
    log = null
  } = app.config;
  let logger;
  if (log) {
    // 更具环境添加环境ke
    const appenders = {};
    const env = app.env || NODE_ENV;
    appenders[env] = log.appender || {};
    if (env === 'development') {
      appenders.dev = {
        type: 'console'
      };
    }

    // @ts-ignore
    log4js.configure({
      appenders,
      categories: {
        default: {
          appenders: Object.keys(appenders),
          level: log.level || 'info' //app.js中设置的level
        }
      },

      // pm2: log.pm2 !== false, // 不为false都为true
      // pm2InstanceVar: 'INSTANCE_ID',
      // disableClustering: true
    });
    logger = log4js.getLogger();
    // LEVELS.forEach(item => {
    //   const loggerFn = logger[item].bind(logger);
    //   if (item === 'info') {
    //     console.log = loggerFn;
    //   }
    //   console[item] = loggerFn;
    // });
  }
  return async (ctx, next) => {
    let ctxLogger = {};
    if (log) {
      LEVELS.forEach(item => {
        ctxLogger[item] = message => {
          logger[item](clientInfo(ctx, message));
        };
      });
    }
    ctx.log = ctxLogger;
    ctx.log.startTime = Date.now();
    await next();

    // 以下是请求日志输出
    const info = clientInfo(ctx);
    if (app.env === 'development') {
      console.info(info);
    } else {
      console.info(Object.values(info).join(' '));
    }
  };
};

function clientInfo(ctx, message = '-') {
  const requestTime = Date.now();
  return {
    ip: ctx.ip,
    method: ctx.method,
    statusCode: ctx.status,
    requestHost: ctx.host,
    requestUrl: encodeURI(ctx.originalUrl),
    referer: encodeURI(ctx.get('referer')) || '-',
    userAgent: encodeURI(ctx.get('user-agent')) || '-',
    requestTime: new Date(requestTime),
    responseTime: (requestTime - ctx.log.startTime) + 'ms',
    requestId: ctx.get('x-request-id') || '-',
    message
  };
};
